
#include "server.h"
#include "adm.h"
#include "manager.h"
#include "worker.h"

//* Function: rp_rpointd_server_init()
//*  	To initialize a Rpointd server
//*
void rp_rpointd_server_init(int argc, char *argv[])
{
	char fname[] ="rp_rpointd_server_init";
	char msg[] = "fatal error";
 	Err err;

	//err = rp_getopt_rpointd(argc, argv);
	rp_rpointd_env_init();
	rp_rpointd_config_init();
	rp_rpointd_log_init();	
	rp_rpointd_global_init();

	FLOG_IN(fname);
	
	/*	Score init    */
	int fd;
	rp_pid_t pid;
	char filename[MAX_FILENAME_LENGTH];
	struct stat fstat;
	
	if (lstat("/tmp/rally", &fstat) < 0) 
	{
		rp_log(LOG_DEBUG, fname, "/tmp/rally does not exist. we are going to create ...");
		if (mkdir("/tmp/rally", 00777) < 0)
		{
			rp_log(LOG_FATAL, fname, "Cannot create /tmp/rally. Error: %s", strerror(errno));
			exit(127);
		}
	}

	pid = getpid();
	memset(filename, 0, MAX_FILENAME_LENGTH);
	sprintf(filename, "/tmp/rally/%d", pid);
	if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 00777)) < 0)		 
	{
		rp_log(LOG_FATAL, fname, "Cannot open the file %s", filename, strerror(errno));
		exit(127);
	} 
	
	lseek(fd, sizeof(Score)-1, SEEK_END);
	write(fd, "", 1);
	if ((global.score = mmap(NULL, sizeof(Score), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
	{
		close(fd);
		rp_log(LOG_FATAL, fname, "Cannot mmap the file %s", filename, strerror(errno));
		exit(127);
	} 
	close(fd);
	err = rp_score_init_pshared(global.score);
	
	/*	event init	   */
	global.evb_server = (struct event_base *)event_init();
	event_set(&global.ev_adm, global.fd_stdin, EV_READ|EV_PERSIST, rp_rpointd_adm, NULL);  
	event_base_set(global.evb_server, &global.ev_adm);
	if (event_add(&global.ev_adm, NULL) < 0)
	{
		rp_log(LOG_FATAL, fname, "Cannot setup the event ...");
		exit(127);
	}
	
	/*	Rpointd Lock init   */
	if ((fd = open("/tmp/rally/rpointd.lock", O_RDWR|O_CREAT, 00777)) < 0)		
	{
		rp_log(LOG_FATAL, fname, "Cannot open the file /tmp/rally/rpointd.lock. Error: %s", strerror(errno));
		exit(127);
	} 
	
	if (mmap(&(global.mutex_hsk), sizeof(rp_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0) == MAP_FAILED)
	{
		close(fd);
		rp_log(LOG_FATAL, fname, "Cannot mmap the /tmp/rally/rpointd.lock. Error: %s", strerror(errno));
		exit(127);
	} 
	close(fd);
	if (rp_mutex_init(&global.mutex_hsk) != E_OK)
	{
		rp_log(LOG_FATAL, fname, "Cannot initialize the handshake mutex ...");
		exit(127);
	}
	
	if (rp_thread_create(&(global.tid_manager), rp_rpointd_manager, NULL) != E_OK)
	{
		rp_log(LOG_FATAL, fname, "Cannot create the manager thread ...");
		exit(127);
	}
	int i, tc = 0;
	Status *status;
	for (i=0; i<config.num_thread_prestart; i++)
	{
		status = global.status_worker+i;
		if (rp_thread_create(&(status->tid), rp_rpointd_worker, NULL) != E_OK)
		{
			rp_log(LOG_DEBUG, fname, "Cannot create a worker thread ...");
		} else {
			tc++;
		}
	}
	rp_log(LOG_DEBUG, fname, "%d worker thread(s) created.", tc);

	FLOG_OUT(fname);
}

void rp_rpointd_server_run()
{
	char fname[] ="rp_rpointd_server_run";
	char msg[] = "fatal error";
	Err err;

	FLOG_IN(fname);
	event_base_dispatch(global.evb_server);
	FLOG_OUT(fname);
}

void rp_rpointd_server_finalize()
{
	char fname[] ="rp_rpointd_server_finalize";
	char msg[] = "fatal error";
	Err err;

	FLOG_IN(fname);
	FLOG_OUT(fname);
}

int main(int argc, char* argv[])
{
	sleep(20);		// TODO:
	rp_rpointd_server_init(argc, argv);
	rp_rpointd_server_run();					// start the Rpointd server
	rp_rpointd_server_finalize();
	
	return 0;
}

